home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-20 / nrd34.zip / SCREEN.PAS < prev    next >
Pascal/Delphi Source File  |  1990-12-01  |  16KB  |  624 lines

  1. {SCREEN.PAS --- rev 2.4
  2.        Author:  Tom Whiteside
  3.                 11505 Oak View Dr
  4.                 Austin, TX 78759
  5.                 (512) 258-5924
  6.  
  7.  
  8.        Purpose: Various screen control, data entry utilities.  These were
  9.                 developed years ago for Apple Pascal and subsequently ported
  10.                 to IBM Pascal then Turbo Pascal to migrate other code along.
  11.                 Their main asset is their use by many lines of code and my
  12.                 familiarity with them. }
  13. {$I-}
  14. {$V-}
  15. unit screen;
  16.  
  17. interface
  18.  
  19.   type
  20.     crtcmd    = (ERASEOS,ERASEOL,UP,DOWN,RIGHT,LEFT);
  21.  
  22.     keycmd    = packed record
  23.             charperline,
  24.             linesperscreen:byte;
  25.             upkey,
  26.             downkey,
  27.             fskey,
  28.             bskey,
  29.             rubkey,
  30.             inskey,
  31.             delkey,
  32.             pgupkey,
  33.             pgdnkey,
  34.             homekey,
  35.             endkey,
  36.             esckey,
  37.                     backtabkey,
  38.                     tabkey,
  39.                     ctrlpgupkey,
  40.                     ctrlpgdnkey:char;
  41.           end;
  42.  
  43.     speakerbeep = (SILENT,BEEP);
  44.  
  45.     scrn_attr    = (UNDERSCORE,BLINK,BROWN,LIGHTGRAY,DARKGRAY,BLACK,
  46.            RED,LIGHTBLUE,LIGHTGREEN,LIGHTCYAN,LIGHTRED,LIGHTMAGENTA,
  47.            GREEN,YELLOW,BLUE,MAGENTA,CYAN,WHITE);
  48.  
  49.     scrn_mode    = (FOREGROUND,BACKGROUND);
  50.  
  51.     lstring    = string[255];
  52.  
  53.   const keyinfo : keycmd =
  54.              (charperline:      80;
  55.               linesperscreen: 25;
  56.               upkey:      chr(15);
  57.               downkey:      chr(11);
  58.               fskey:      chr(21);
  59.               bskey:      chr(7);
  60.               rubkey:      chr(8);
  61.               inskey:      chr(1);
  62.               delkey:      chr(2);
  63.               pgupkey:      chr(3);
  64.               pgdnkey:      chr(4);
  65.               homekey:      chr(5);
  66.               endkey:      chr(6);
  67.               esckey:      chr(27);
  68.                           backtabkey:     chr(10);
  69.                           tabkey:         chr(9);
  70.                           ctrlpgupkey:    chr(14);
  71.                           ctrlpgdnkey:    chr(16));
  72.  
  73.   procedure call_crt(cmd:crtcmd); { this was crt in the IBM Pascal vers }
  74.   procedure home;
  75.   procedure gotoxy_old(x,y:integer); { change this in source from gotoxy }
  76.   function  fetch:char;
  77.   procedure bell;
  78.   procedure entnum(x,y:integer; var val:integer; var ok,nullval:boolean;
  79.                message:lstring);
  80.   procedure prompt(promptln:lstring; var rtncmd:char; ring:speakerbeep;
  81.                defrec:integer);
  82.   procedure hndlerr(abor:boolean; var escape:char; rslt:integer);
  83.   function  keypress:boolean;
  84.   procedure writea(attr:scrn_attr; mode:scrn_mode);
  85.   procedure show_line(x,y,fieldlen:integer; val:lstring; edit:boolean);
  86.   procedure editfield(x,y,fieldlen:integer; number:boolean; var val:lstring);
  87.  
  88. implementation
  89.  
  90.  
  91.   uses crt,strutil,intutil;
  92.  
  93.  
  94.   const CARRET = chr(13);  {carriage return}
  95.  
  96.   type monitortype = (BW_MON,COLOR_MON);
  97.  
  98.   var  monitor: monitortype;
  99.        screenbuf: text;
  100.  
  101.  
  102.   procedure call_crt;
  103.   var j,k,x,y,lines,chars:integer;
  104.   begin { call_crt }
  105.     x:=wherex; y:=wherey;
  106.     lines:=ord(keyinfo.linesperscreen);
  107.     chars:=ord(keyinfo.charperline);
  108.     case cmd of
  109.       UP:    gotoxy(x, maxi(1,y - 1));
  110.       DOWN:    gotoxy(x, mini(lines,y + 1));
  111.       RIGHT:    gotoxy(mini(chars,x + 1), y);
  112.       LEFT:    gotoxy(maxi(1,x - 1), y);
  113.       ERASEOL:    clreol;
  114.       ERASEOS:    begin
  115.           k:=x;
  116.           { erase from cursor position down }
  117.           for j:=y to lines do
  118.             begin
  119.               gotoxy(k,j);
  120.               call_crt(ERASEOL);
  121.               k:=0; { reset "x" place holder after 1rst line }
  122.             end;
  123.           gotoxy(x,y);
  124.         end;
  125.     end; { cases }
  126.   end; { call_crt }
  127.  
  128.  
  129.   procedure home;
  130.   begin
  131.     clrscr;
  132.   end;
  133.  
  134.   procedure gotoxy_old; { IBM Pascal had upper left at 0,0 }
  135.   begin
  136.     gotoxy(x + 1,y + 1);
  137.   end;
  138.  
  139.   function fetch;
  140.   var ch:char;
  141.   begin
  142.     ch:=readkey;
  143.     if ord(ch) = 0 then { fetch extended function }
  144.       begin
  145.     ch:=readkey;
  146.     case ord(ch) of
  147.       71:ch:=keyinfo.homekey;
  148.       72:ch:=keyinfo.upkey;
  149.       73:ch:=keyinfo.pgupkey;
  150.       75:ch:=keyinfo.bskey;
  151.       77:ch:=keyinfo.fskey;
  152.       79:ch:=keyinfo.endkey;
  153.       80:ch:=keyinfo.downkey;
  154.       81:ch:=keyinfo.pgdnkey;
  155.       82:ch:=keyinfo.inskey;
  156.       83:ch:=keyinfo.delkey;
  157.           15:ch:=keyinfo.backtabkey;
  158.          118:ch:=keyinfo.ctrlpgdnkey;
  159.          132:ch:=keyinfo.ctrlpgupkey;
  160.     else ch:=chr(0);
  161.     end;
  162.       end;
  163.     fetch:=ch;
  164.   end;
  165.  
  166.   procedure bell;
  167.   begin
  168.     write(chr(7));
  169.   end;
  170.  
  171.  
  172.   function keypress;
  173.   { mapped for compatibility }
  174.   begin
  175.     keypress:=keypressed;
  176.   end;
  177.  
  178.   procedure prompt;
  179.   begin
  180.     gotoxy(1,1); clreol;
  181.     if ring = BEEP then { beep and flush key buffer }
  182.       begin
  183.     writea(LIGHTRED,FOREGROUND);
  184.     bell;
  185.     while keypress do rtncmd:=fetch;
  186.       end
  187.     else
  188.       begin
  189.     writea(LIGHTGREEN,FOREGROUND);
  190.       end;
  191.     write(promptln);
  192.     if defrec > 0 then write(' [',defrec:0,']');
  193.     gotoxy(ord(keyinfo.charperline) + 1,1);
  194.     rtncmd:=fetch;
  195.     if (rtncmd in ['a'..'z']) then { capitalize }
  196.        rtncmd:=chr(ord(rtncmd) + ord('A') - ord('a'));
  197.     writea(LIGHTGRAY,FOREGROUND);
  198.   end;
  199.  
  200.   procedure hndlerr;
  201.  
  202.     procedure ems(rslt:integer; t:lstring);
  203.     begin
  204.       call_crt(ERASEOS);
  205.       writeln; bell;
  206.       writea(LIGHTRED,FOREGROUND);
  207.       writeln('Error #',rslt:4,' ',t);
  208.       writea(LIGHTGRAY,FOREGROUND);
  209.       writeln;
  210.       write('Type <SPACE> to continue');
  211.       if not abor then write(' <ESC> to cancel command');
  212.       escape:=fetch;
  213.       writeln;
  214.       if (escape in ['a'..'z']) then { capitalize }
  215.     escape:=chr(ord(escape) + ord('A') - ord('a'));
  216.     end; { ems }
  217.  
  218.   begin { hndlerr }
  219.     case rslt of
  220.        0:;   { no error }
  221.      1:  ems(rslt,'Invalid function Error');
  222.      2:  ems(rslt,'File not found');
  223.      3:  ems(rslt,'Path not found');
  224.      4:  ems(rslt,'Too many open files');
  225.      5:  ems(rslt,'File access denied');
  226.      6:  ems(rslt,'Invalid file handle');
  227.     12:  ems(rslt,'Invalid file access code');
  228.     15:  ems(rslt,'Invalid drive number');
  229.     16:  ems(rslt,'Cannot remove current directory');
  230.     17:  ems(rslt,'Cannot rename across drives');
  231.        100:  ems(rslt,'Disk Error');
  232.        101:  ems(rslt,'Disk Write Error');
  233.        102:  ems(rslt,'File not assigned');
  234.        103:  ems(rslt,'File not open');
  235.        104:  ems(rslt,'File not open for input');
  236.        105:  ems(rslt,'File not open for output');
  237.        106:  ems(rslt,'Invalid numeric format');
  238.        150:  ems(rslt,'Disk is write protected');
  239.        151:  ems(rslt,'Unknown unit');
  240.        152:  ems(rslt,'Drive not ready');
  241.        153:  ems(rslt,'Unknown command');
  242.        154:  ems(rslt,'CRC error in data');
  243.        155:  ems(rslt,'Bad drive request structure length');
  244.        156:  ems(rslt,'Disk seek error');
  245.        157:  ems(rslt,'Unknown media type');
  246.        158:  ems(rslt,'Sector not found');
  247.        159:  ems(rslt,'Printer out of paper');
  248.        160:  ems(rslt,'Device write fault');
  249.        161:  ems(rslt,'Device read fault');
  250.        162:  ems(rslt,'Hardware failure');
  251.        else  ems(rslt,'Undefined error');
  252.     end; { cases }
  253.   end;    { hndlerr }
  254.  
  255.  
  256.   procedure writea;
  257.   var i:integer;
  258.   begin
  259.     case monitor of
  260.       COLOR_MON:
  261.      case mode of
  262.         FOREGROUND:
  263.           begin
  264.         case attr of
  265.           BLINK       :textcolor(textattr+128);
  266.           BLACK       :textcolor(0);
  267.           BROWN       :textcolor(6);
  268.           LIGHTGRAY   :textcolor(7);
  269.           DARKGRAY    :textcolor(8);
  270.           LIGHTBLUE   :textcolor(9);
  271.           LIGHTGREEN  :textcolor(10);
  272.           LIGHTCYAN   :textcolor(11);
  273.           LIGHTRED    :textcolor(12);
  274.           LIGHTMAGENTA:textcolor(13);
  275.           RED          :textcolor(4);
  276.           GREEN       :textcolor(2);
  277.           YELLOW      :textcolor(14);
  278.           BLUE          :textcolor(1);
  279.           MAGENTA     :textcolor(5);
  280.           CYAN          :textcolor(3);
  281.           WHITE       :textcolor(15);
  282.         end; { cases }
  283.           end;
  284.         BACKGROUND:
  285.           begin
  286.         case attr of
  287.           BLACK      :textbackground(0);
  288.           RED         :textbackground(4);
  289.           GREEN      :textbackground(2);
  290.           YELLOW     :textbackground(6); { brown }
  291.           BLUE         :textbackground(1);
  292.           MAGENTA    :textbackground(5);
  293.           CYAN         :textbackground(3);
  294.           WHITE      :textbackground(7); { grey }
  295.         end; { cases }
  296.           end;
  297.     end;
  298.       BW_MON:
  299.      case mode of
  300.         FOREGROUND:
  301.           begin
  302.         case attr of
  303.           BLINK      :textcolor(textattr+128);
  304.           BLACK      :textcolor(0);
  305.           WHITE      :textcolor(15);
  306.         end; { cases }
  307.           end;
  308.         BACKGROUND:
  309.           begin
  310.         case attr of
  311.           BLACK      :textbackground(0);
  312.           WHITE      :textbackground(7); { grey }
  313.         end; { cases }
  314.           end;
  315.      end;
  316.        end;
  317.   end;
  318.  
  319.  
  320.   procedure show_line;
  321.   var i:integer;
  322.       lf_bracket,rt_bracket:char;
  323.   begin { show_line }
  324.     gotoxy(x,y + 1); call_crt(ERASEOL);
  325.     if edit then { they are editing this line }
  326.       begin
  327.     lf_bracket:='[';
  328.     rt_bracket:=']';
  329.     writea(BLUE,BACKGROUND);
  330.     writea(YELLOW,FOREGROUND);
  331.       end
  332.     else
  333.       begin
  334.     writea(BLACK,BACKGROUND);
  335.     writea(LIGHTGRAY,FOREGROUND);
  336.     lf_bracket:=' ';
  337.     rt_bracket:=' ';
  338.       end;
  339.     write(lf_bracket,val);
  340.     gotoxy(x + 1 + fieldlen,y + 1);
  341.     write(rt_bracket);
  342.   end;    { show_line }
  343.  
  344.  
  345.   procedure edfield(x,y,fieldlen:integer; number:boolean; var val:lstring;
  346.              var ok:boolean);
  347.  
  348.   { parameters: x,y     = cursor position
  349.         fieldlen = allowable length for field
  350.         number     = flag that if true restricts the keys usable
  351.         val     = return string
  352.         ok     = TRUE if the user did not hit escape    }
  353.  
  354.   var ptr,i:integer;
  355.       ch:char;
  356.       errflg,flag,insert_mode:boolean;
  357.       oldval:string[255];
  358.  
  359.  
  360.     procedure errmsg(message:lstring);
  361.     var ch:char;
  362.     begin
  363.       errflg:=TRUE;
  364.       bell;
  365.       while keypress do ch:=fetch; { flush keyboard buffer }
  366.       writea(LIGHTGRAY,FOREGROUND);
  367.       show_line(x,y,fieldlen,val,TRUE); { re-display line }
  368.       gotoxy(x + fieldlen + 6,y + 1);
  369.       writea(RED,FOREGROUND);
  370.       write(message);
  371.       writea(BLUE,BACKGROUND);
  372.       writea(YELLOW,FOREGROUND);
  373.       gotoxy(x + 1 + ptr,y + 1);
  374.     end;
  375.  
  376.     procedure clrerr(var errflg:boolean) ;
  377.     { erase error message at the right of screen }
  378.     begin
  379.       if errflg then
  380.     begin
  381.       errflg:=FALSE;
  382.       writea(LIGHTGRAY,FOREGROUND);
  383.       writea(BLACK,BACKGROUND);
  384.       gotoxy(x + fieldlen + 5,y + 1);  call_crt(ERASEOL);
  385.       gotoxy(x + 1 + ptr,y + 1);
  386.       writea(BLUE,BACKGROUND);
  387.       writea(YELLOW,FOREGROUND);
  388.     end;
  389.     end;
  390.  
  391.     procedure blankfill(fieldlen:integer; var val:lstring);
  392.     begin
  393.       while length(val) < fieldlen do val:=concat(val,' ');
  394.     end;
  395.  
  396.  
  397.     procedure get_normal;
  398.  
  399.     { fetch normal character and display it.  Handle field overflow and
  400.       insert_mode }
  401.  
  402.     var i:integer;
  403.     s:string[1];
  404.     begin
  405.       if ptr < fieldlen
  406.     then
  407.       begin
  408.         if ((number) and (ch in ['0'..'9',' ','.']))
  409.         or ((ptr = 0) and (ch = '-')) or not number then
  410.           begin { all's well }
  411.         if not insert_mode then
  412.           begin
  413.             write(ch); { echo character to screen }
  414.             ptr:=ptr + 1;
  415.             val[ptr]:=ch
  416.           end
  417.         else { handle insert mode }
  418.           begin
  419.             ptr:=ptr + 1;
  420.             for i:=fieldlen downto ptr do val[i]:=val[i - 1];
  421.             val[ptr]:=ch;
  422.             for i:=ptr to fieldlen do write(val[i]);
  423.             gotoxy(x + ptr + 1,y + 1);
  424.           end
  425.           end
  426.         else errmsg('Key not a number')
  427.       end
  428.     else errmsg('Max characters entered')
  429.     end; { get_normal }
  430.  
  431.     procedure do_backspace;
  432.     begin
  433.       if ptr > 0 then { it's ok to backspace }
  434.     begin
  435.       ptr:=ptr - 1;
  436.       gotoxy(x + ptr + 1,y + 1)
  437.     end
  438.       else errmsg('Please stay right of ''[''')
  439.     end;
  440.  
  441.     procedure do_forwardspace;
  442.     begin
  443.       if ptr < fieldlen then { its ok to forward space }
  444.     begin
  445.       ptr:=ptr + 1;
  446.       gotoxy(x + ptr + 1,y + 1)
  447.     end
  448.       else errmsg('Please stay left of '']''')
  449.     end;
  450.  
  451.     procedure do_del;
  452.     var i:integer;
  453.     begin
  454.       for i:=ptr + 1 to fieldlen - 1 do val[i]:=val[i + 1];
  455.       val[fieldlen]:=' ';
  456.       for i:=ptr + 1 to fieldlen do write(val[i]);
  457.       gotoxy(x + ptr + 1,y + 1);
  458.     end;
  459.  
  460.     procedure do_rub;
  461.     var i:integer;
  462.     begin
  463.       if ptr > 0 then ptr:=ptr - 1;
  464.       gotoxy(x + ptr + 1,y + 1);
  465.       do_del;
  466.     end;
  467.  
  468.     procedure toggle_insert;
  469.     begin
  470.       insert_mode:=not insert_mode;
  471.       writea(LIGHTGRAY,FOREGROUND);
  472.       gotoxy(31,25);
  473.       if insert_mode then
  474.     begin
  475.       writea(RED,FOREGROUND);
  476.       write('Insert');
  477.     end
  478.       else call_crt(ERASEOL);
  479.       gotoxy(x + 1 + ptr,y + 1);
  480.       writea(BLUE,BACKGROUND);
  481.       writea(YELLOW,FOREGROUND);
  482.    end;
  483.  
  484.    procedure do_esc;
  485.    begin
  486.      val:=oldval;
  487.      ok:=FALSE;
  488.    end;
  489.  
  490.    procedure do_home;
  491.    begin
  492.      ptr:=0;
  493.      gotoxy(x + ptr + 1,y + 1)
  494.    end;
  495.  
  496.    procedure do_end;
  497.    begin
  498.      ptr:=fieldlen;
  499.      while (ptr > 0) and (val[ptr] = ' ') do
  500.        ptr:=ptr - 1;
  501.      gotoxy(x + ptr + 1,y + 1)
  502.    end;
  503.  
  504.   begin { edfield }
  505.     insert_mode:=FALSE;
  506.     ok:=TRUE;
  507.     if number and (val = '-0.00') then val:='0.00';
  508.     oldval:=val; { save copy in case they abort }
  509.     blankfill(fieldlen,val);
  510.     ptr:=0;
  511.     show_line(x,y,fieldlen,val,TRUE);
  512.     gotoxy(x + 1,y + 1);
  513.     repeat
  514.       ch:=fetch;
  515.       clrerr(errflg);
  516.       if (ch <> CARRET) and (ord(ch) >= ord(' ')) then get_normal
  517.       else if ch = keyinfo.bskey   then do_backspace
  518.       else if ch = keyinfo.fskey   then do_forwardspace
  519.       else if ch = keyinfo.delkey  then do_del
  520.       else if ch = keyinfo.rubkey  then do_rub
  521.       else if ch = keyinfo.inskey  then toggle_insert
  522.       else if ch = keyinfo.esckey  then do_esc
  523.       else if ch = keyinfo.homekey then do_home
  524.       else if ch = keyinfo.endkey  then do_end
  525.       else if ch <> CARRET       then errmsg('Invalid Character');
  526.     until (ch = CARRET) or (ch = keyinfo.esckey);
  527.  
  528.     if number then { strip off trailing blanks }
  529.       begin
  530.     ptr:=length(val);
  531.     flag:=TRUE;
  532.     while (ptr > 0) and flag do
  533.       begin
  534.         flag:=val[ptr] = ' ';
  535.         if flag then delete(val,ptr,1);
  536.         ptr:=ptr - 1;
  537.       end;
  538.       end;
  539.     writea(LIGHTGRAY,FOREGROUND);
  540.     writea(BLACK,BACKGROUND);
  541.     gotoxy(1,25); call_crt(ERASEOL);
  542.     show_line(x,y,fieldlen,val,FALSE);
  543.   end; { edfield }
  544.  
  545.  
  546.   procedure editfield;
  547.   var dummy:boolean;
  548.   begin
  549.     { normal editfield but ignore dummy (TRUE if user hit ESC) }
  550.     edfield(x,y,fieldlen,number,val,dummy);
  551.   end;
  552.  
  553.   procedure entnum;
  554.   var s1,s2:lstring;
  555.       s3:string[255];
  556.       i,j:integer;
  557.       bogus:boolean;
  558.   begin
  559.     s1:=''; ok:=TRUE;
  560.     bogus:=TRUE;  { Guilty until proven innocent }
  561.     s3:=concat('Enter ',message,' number <ESC> quits: ');
  562.     gotoxy(x + 1,y + 1); call_crt(ERASEOL);
  563.     writea(LIGHTGREEN,FOREGROUND);
  564.     write(s3);
  565.     while bogus do
  566.       begin
  567.     bogus:=FALSE;
  568.     edfield(x + length(s3),y,5,TRUE,s1,ok);
  569.     j:=1;
  570.     val:=0;
  571.     nullval:=(s1 = '');
  572.     if not nullval and ok then for i:=length(s1) downto 1 do
  573.       begin
  574.         if not (s1[i] in ['-','0'..'9']) then bogus:=TRUE
  575.         else
  576.           begin
  577.         if s1[i] = '-' then val:=-val
  578.         else
  579.           begin
  580.             val:=val + (ord(s1[i]) - ord('0')) * j;
  581.             j:=j * 10
  582.           end
  583.           end
  584.       end
  585.       end
  586.   end;
  587.  
  588.   procedure initcrtinfo; { find out whether user has a BW or color monitor }
  589.   var f:text;
  590.       ch:char;
  591.       err:word;
  592.  
  593.   begin
  594.     monitor:=BW_MON;
  595.     assign(f,'@MONITOR.DAT');
  596.     reset(f);  { expect a file not found error }
  597.     err:=ioresult;
  598.     if err = 0 then
  599.       begin
  600.     read(f,ch); { read color attribute }
  601.     close(f);
  602.       end
  603.     else { ok to write the result }
  604.       begin
  605.     close(f);
  606.     rewrite(f);
  607.     err:=ioresult;
  608.     home;
  609.     prompt('To use color in this program, type ''C'' otherwise hit ENTER'
  610.           ,ch,SILENT,0);
  611.     write(f,ch);
  612.     err:=ioresult; hndlerr(TRUE,ch,err);
  613.     close(f);
  614.     err:=ioresult; hndlerr(TRUE,ch,err);
  615.       end;
  616.       if ch = 'C' then monitor:=COLOR_MON;
  617.     assigncrt(screenbuf);
  618.   end;
  619.  
  620.  
  621. begin { screen }
  622.   initcrtinfo
  623. end.
  624.